package handler

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/olivere/elastic/v7"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"google.golang.org/protobuf/types/known/emptypb"
	"mxshop_srvs/goods_srv/global"
	"mxshop_srvs/goods_srv/model"
	"mxshop_srvs/goods_srv/proto"
)

// GoodsServer 定义商品服务
type GoodsServer struct{}

// GoodsList 获取商品列表
func (g *GoodsServer) GoodsList(_ context.Context, in *proto.GoodsFilterRequest) (*proto.GoodsListResponse, error) {
	// 实现获取商品列表的逻辑
	// 关键词搜索、查询新品、查询热门商品、通过价格区间筛选、通过商品分类筛选。
	goodsListResponse := &proto.GoodsListResponse{}

	// match bool 符合查询

	q := elastic.NewBoolQuery()
	localDB := global.DB.Model(&model.Goods{}) // 全局变量DB
	if in.KeyWords != "" {
		//localDB = localDB.Where("name like ?", "%"+in.KeyWords+"%")
		q = q.Must(elastic.NewMultiMatchQuery(in.KeyWords, "name", "goods_brief"))
	}
	if in.IsNew {
		//localDB = localDB.Where(model.Goods{IsNew: true})
		q = q.Filter(elastic.NewTermQuery("is_new", true))
	}
	if in.IsHot {
		//localDB = localDB.Where(model.Goods{IsHot: true})
		q = q.Filter(elastic.NewTermQuery("is_hot", true))
	}
	if in.PriceMin > 0 {
		//localDB = localDB.Where("shop_price >= ?", in.PriceMin)
		q = q.Filter(elastic.NewRangeQuery("shop_price").Gte(in.PriceMin))
	}
	if in.PriceMax > 0 {
		//localDB = localDB.Where("shop_price <= ?", in.PriceMax)
		q = q.Filter(elastic.NewRangeQuery("shop_price").Lte(in.PriceMax))
	}
	if in.Brand > 0 {
		//localDB = localDB.Where("brand_id = ?", in.Brand)
		q = q.Filter(elastic.NewTermQuery("brand_id", in.Brand))
	}
	// 通过商品分配筛选
	categoryIds := make([]interface{}, 0)
	if in.TopCategory > 0 {
		var category model.Category
		if result := global.DB.First(&category, in.TopCategory); result.RowsAffected == 0 {
			return nil, status.Error(codes.NotFound, "商品分类不存在")
		}
		var subQuery string
		if category.Level == 1 {
			subQuery = fmt.Sprintf("select id from category where parent_category_id in (select id from category where parent_category_id = %d)", in.TopCategory)
		} else if category.Level == 2 {
			subQuery = fmt.Sprintf("select id from category where parent_category_id = %d", in.TopCategory)
		} else {
			subQuery = fmt.Sprintf("select id from category where id = %d", in.TopCategory)
		}
		type Result struct {
			ID int32 `json:"id"`
		}
		var results []Result
		global.DB.Model(&model.Category{}).Raw(subQuery).Scan(&results)
		for _, result := range results {
			categoryIds = append(categoryIds, result.ID)
		}
		//localDB = localDB.Where(fmt.Sprintf("category_id in (%s)", subQuery))

		q.Filter(elastic.NewTermsQuery("category_id", categoryIds...))
	}

	// 分页
	if in.Pages == 0 {
		in.Pages = 1
	}
	switch {
	case in.PagePerNums > 100:
		in.PagePerNums = 100
	case in.PagePerNums <= 0:
		in.PagePerNums = 10
	}

	result, err := global.EsClient.Search().Index(model.EsGoods{}.GetIndexName()).Query(q).From(int(in.Pages)).Size(int(in.PagePerNums)).Do(context.Background())
	if err != nil {
		return nil, err
	}
	goodsIds := make([]int32, 0)
	goodsListResponse.Total = int32(result.Hits.TotalHits.Value)
	for _, hit := range result.Hits.Hits {
		goods := model.EsGoods{}
		_ = json.Unmarshal(hit.Source, &goods)
		goodsIds = append(goodsIds, goods.ID)
	}

	// 查询id在某个数组中的值
	var goodss []model.Goods
	re := localDB.Preload("Category").Preload("Brands").Find(&goodss, goodsIds)
	if re.Error != nil {
		return nil, status.Error(codes.Internal, "获取商品列表失败")
	}
	for _, good := range goodss {
		goodsInfoResponse := Model2Response(good)
		goodsListResponse.Data = append(goodsListResponse.Data, &goodsInfoResponse)
	}
	return goodsListResponse, nil
}
func Model2Response(goods model.Goods) proto.GoodsInfoResponse {
	return proto.GoodsInfoResponse{
		Id:             goods.ID,
		CategoryId:     goods.CategoryID,
		Name:           goods.Name,
		GoodsSn:        goods.GoodsSn,
		ClickNum:       goods.ClickNum,
		SoldNum:        goods.SoldNum,
		FavNum:         goods.FavNum,
		MarketPrice:    goods.MarketPrice,
		ShopPrice:      goods.ShopPrice,
		GoodsBrief:     goods.GoodsBrief,
		ShipFree:       goods.ShipFree,
		GoodFrontImage: goods.GoodsFrontImage,
		IsNew:          goods.IsNew,
		IsHot:          goods.IsHot,
		OnSale:         goods.OnSale,
		DescImages:     goods.DescImages,
		Images:         goods.Images,
		Category: &proto.CategoryBriefInfoResponse{
			Id:   goods.Category.ID,
			Name: goods.Category.Name,
		},
		Brand: &proto.BrandInfoResponse{
			Id:   goods.Brands.ID,
			Name: goods.Brands.Name,
			Logo: goods.Brands.Logo,
		},
	}
}

// BatchGetGoods 批量获取商品信息
func (g *GoodsServer) BatchGetGoods(_ context.Context, in *proto.BatchGoodsIdInfo) (*proto.GoodsListResponse, error) {
	// 实现批量获取商品信息的逻辑
	goods := []model.Goods{}
	result := global.DB.Where(in.Id).Find(&goods)
	goodsListResponse := &proto.GoodsListResponse{}
	for _, good := range goods {
		goodsInfoResponse := Model2Response(good)
		goodsListResponse.Data = append(goodsListResponse.Data, &goodsInfoResponse)
	}
	goodsListResponse.Total = int32(result.RowsAffected)
	return goodsListResponse, nil
}

// CreateGoods 创建商品
func (g *GoodsServer) CreateGoods(_ context.Context, in *proto.CreateGoodsInfo) (*proto.GoodsInfoResponse, error) {
	// 实现创建商品的逻辑
	var category model.Category
	if result := global.DB.First(&category, in.CategoryId); result.RowsAffected == 0 {
		return nil, status.Errorf(codes.NotFound, "商品分类不存在")
	}
	var brands model.Brands
	if result := global.DB.First(&brands, in.BrandId); result.RowsAffected == 0 {
		return nil, status.Errorf(codes.NotFound, "品牌不存在")
	}
	goods := model.Goods{
		Category:        category,
		CategoryID:      in.CategoryId,
		Brands:          brands,
		BrandsID:        in.BrandId,
		Name:            in.Name,
		GoodsSn:         in.GoodsSn,
		MarketPrice:     in.MarketPrice,
		ShopPrice:       in.ShopPrice,
		GoodsBrief:      in.GoodsBrief,
		ShipFree:        in.ShipFree,
		Images:          in.Images,
		DescImages:      in.DescImages,
		GoodsFrontImage: in.GoodFrontImage,
		IsNew:           in.IsNew,
		IsHot:           in.IsHot,
		OnSale:          in.OnSale,
	}
	tx := global.DB.Begin()
	result := tx.Save(&goods)
	if result.Error != nil {
		tx.Rollback()
		return nil, result.Error
	}
	tx.Commit()

	return &proto.GoodsInfoResponse{Id: goods.ID}, nil
}

// DeleteGoods 删除商品
func (g *GoodsServer) DeleteGoods(_ context.Context, in *proto.DeleteGoodsInfo) (*emptypb.Empty, error) {
	// 实现删除商品的逻辑
	if result := global.DB.Delete(&model.Goods{BaseModel: model.BaseModel{ID: in.Id}}, in.Id); result.RowsAffected == 0 {
		return nil, status.Errorf(codes.NotFound, "商品不存在")
	}
	return &emptypb.Empty{}, nil
}

// UpdateGoods 更新商品
func (g *GoodsServer) UpdateGoods(_ context.Context, in *proto.CreateGoodsInfo) (*emptypb.Empty, error) {
	// 实现更新商品的逻辑
	var goods model.Goods
	if result := global.DB.Delete(&model.Goods{}, in.Id); result.RowsAffected == 0 {
		return nil, status.Errorf(codes.NotFound, "商品不存在")
	}
	var category model.Category
	if result := global.DB.First(&category, in.CategoryId); result.RowsAffected == 0 {
		return nil, status.Errorf(codes.NotFound, "商品分类不存在")
	}
	var brands model.Brands
	if result := global.DB.First(&brands, in.BrandId); result.RowsAffected == 0 {
		return nil, status.Errorf(codes.NotFound, "品牌不存在")
	}
	goods.ID = in.Id
	goods.Brands = brands
	goods.BrandsID = brands.ID
	goods.Category = category
	goods.CategoryID = category.ID
	goods.Name = in.Name
	goods.GoodsSn = in.GoodsSn
	goods.MarketPrice = in.MarketPrice
	goods.ShopPrice = in.ShopPrice
	goods.Images = in.Images
	goods.DescImages = in.DescImages
	goods.GoodsFrontImage = in.GoodFrontImage
	goods.IsNew = in.IsNew
	goods.IsHot = in.IsHot
	goods.OnSale = in.OnSale
	goods.GoodsBrief = in.GoodsBrief

	tx := global.DB.Begin()
	result := tx.Omit("add_time").Save(&goods)
	if result.Error != nil {
		tx.Rollback()
		return nil, result.Error
	}
	tx.Commit()
	return &emptypb.Empty{}, nil
}

// GetGoodsDetail 获取商品详情
func (g *GoodsServer) GetGoodsDetail(_ context.Context, in *proto.GoodInfoRequest) (*proto.GoodsInfoResponse, error) {
	// 实现获取商品详情的逻辑
	goods := model.Goods{}
	if result := global.DB.Preload("Category").Preload("Brands").First(&goods, in.Id); result.RowsAffected == 0 {
		return nil, status.Errorf(codes.NotFound, "商品不存在")
	}
	goodsInfoResponse := Model2Response(goods)
	return &goodsInfoResponse, nil
}
